/*
 * @(#)TimeClassTransformer.java   09/10/11
 * 
 * Copyright (C) 2009 Ecole des Mines d'Ales
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: yulinz88@gmail.com
 */



package fr.ema.arch3d.ref.interceptors.asm;

import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.fractal.julia.asm.ClassTransformer;

//~--- classes ----------------------------------------------------------------

/**
 * This class transformer inserts call to "getField" and "setField" methods
 * before each read and write field access instructions in the class it visits.
 */
public class TimeClassTransformer extends ClassAdapter implements ClassTransformer {

    /** Field description */
    private String className;

    /**
     * Constructs ...
     *
     */
    public TimeClassTransformer() {
        super(null);
    }

    /**
     * Method description
     *
     * @param cv  
     */
    public void setClassVisitor(final ClassVisitor cv) {
        this.cv = cv;
    }

    /**
     * Method description
     *
     * @param version  
     * @param access  
     * @param name  
     * @param signature  
     * @param superName  
     * @param interfaces  
     */
    public void visit(final int version, final int access, final String name, final String signature,
                      final String superName, final String[] interfaces) {
        cv.visit(version, access, name, signature, superName, interfaces);
        this.className = name;
    }

    /**
     * Method description
     *
     * @param access  
     * @param name  
     * @param desc  
     * @param signature  
     * @param exceptions  
     * @return  
     */
    public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature,
                                     final String[] exceptions) {
        MethodVisitor v = cv.visitMethod(access, name, desc, signature, exceptions);

        if (v != null) {
            v = new TimeMethodTransformer(className, v);
        }

        return v;
    }

    /**
     * Class description
     *
     *
     * @version        1.0, 09/09/13
     * @author         Huaxi (Yulin) ZHANG
     */
    private static class TimeMethodTransformer extends MethodAdapter implements Opcodes {

        /** Field description */
        private String className;

        /**
         * Constructs ...
         *
         *
         * @param className
         * @param c
         */
        public TimeMethodTransformer(final String className, final MethodVisitor c) {
            super(c);
            this.className = className;
        }

        /**
         * Method description
         *
         * @param opcode  
         * @param owner  
         * @param name  
         * @param desc  
         */
        public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
            mv.visitFieldInsn(opcode, owner, name, desc);
        }
    }
}
